import { Plane } from "../../thirdparty/three/exports";
import { Material, Side, sideNames, sideValues, stencilFuncNames, stencilFuncValues, stencilOpNames, stencilOpValues } from "../../thirdparty/three/imports";

export class Material3D
{
    get _material()
    {
        return this.__material;
    }
    set _material(v)
    {
        Material3D._map.delete(this.__material);
        this.__material = v;
        Material3D._map.set(this.__material, this);
    }
    private __material: Material;

    get side()
    {
        return sideNames[this._material.side];
    }

    set side(v: Side)
    {
        this._material.side = sideValues[v];
    }

    get depthWrite()
    {
        return this._material.depthWrite;
    }
    set depthWrite(v)
    {
        this._material.depthWrite = v;
    }

    get opacity()
    {
        return this._material.opacity;
    }
    set opacity(v)
    {
        this._material.opacity = v;
    }

    get transparent()
    {
        return this._material.transparent;
    }
    set transparent(v)
    {
        this._material.transparent = v;
    }

    get clippingPlanes(): Plane[]
    {
        return this._material.clippingPlanes;
    }
    set clippingPlanes(v)
    {
        this._material.clippingPlanes = v;
    }

    get clipIntersection()
    {
        return this._material.clipIntersection;
    }
    set clipIntersection(v)
    {
        this._material.clipIntersection = v;
    }

    get clipShadows()
    {
        return this._material.clipShadows;
    }
    set clipShadows(v)
    {
        this._material.clipShadows = v;
    }

    get depthTest()
    {
        return this._material.depthTest;
    }
    set depthTest(v)
    {
        this._material.depthTest = v;
    }

    get colorWrite()
    {
        return this._material.colorWrite;
    }
    set colorWrite(v)
    {
        this._material.colorWrite = v;
    }

    get stencilWrite()
    {
        return this._material.stencilWrite;
    }
    set stencilWrite(v)
    {
        this._material.stencilWrite = v;
    }

    get stencilRef()
    {
        return this._material.stencilRef;
    }
    set stencilRef(v)
    {
        this._material.stencilRef = v;
    }

    get stencilFunc()
    {
        return stencilFuncNames[this._material.stencilFunc];
    }
    set stencilFunc(v)
    {
        this._material.stencilFunc = stencilFuncValues[v];
    }

    get stencilFail()
    {
        return stencilOpNames[this._material.stencilFail];
    }
    set stencilFail(v)
    {
        this._material.stencilFail = stencilOpValues[v];
    }

    get stencilZFail()
    {
        return stencilOpNames[this._material.stencilZFail];
    }
    set stencilZFail(v)
    {
        this._material.stencilZFail = stencilOpValues[v];
    }

    get stencilZPass()
    {
        return stencilOpNames[this._material.stencilZPass];
    }
    set stencilZPass(v)
    {
        this._material.stencilZPass = stencilOpValues[v];
    }

    get shadowSide()
    {
        return sideNames[this._material.shadowSide];
    }
    set shadowSide(v)
    {
        this._material.shadowSide = sideValues[v];
    }

    get polygonOffset()
    {
        return this._material.polygonOffset;
    }
    set polygonOffset(v)
    {
        this._material.polygonOffset = v;
    }

    get polygonOffsetFactor()
    {
        return this._material.polygonOffsetFactor;
    }
    set polygonOffsetFactor(v)
    {
        this._material.polygonOffsetFactor = v;
    }

    get polygonOffsetUnits()
    {
        return this._material.polygonOffsetUnits;
    }
    set polygonOffsetUnits(v)
    {
        this._material.polygonOffsetUnits = v;
    }

    get vertexColors()
    {
        return this._material.vertexColors;
    }
    set vertexColors(v)
    {
        this._material.vertexColors = v;
    }

    get alphaTest()
    {
        return this._material.alphaTest;
    }
    set alphaTest(v)
    {
        this._material.alphaTest = v;
    }

    dispose()
    {
        this._material?.dispose();
    }

    destroy()
    {
        this._material?.dispose();
    }

    static get(material: Material)
    {
        let material3D = this._map.get(material);
        if (!material3D)
        {
            material3D = new Material3D();
            material3D._material = material;
        }

        return material3D;
    }
    protected static _map = new Map<Material, Material3D>();
}
